/*
 * Copyright 2002-2019 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.web.servlet.mvc.method.annotation;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.xml.transform.Source;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.core.MethodIntrospector;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.core.task.SimpleAsyncTaskExecutor;
import org.springframework.http.converter.ByteArrayHttpMessageConverter;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter;
import org.springframework.http.converter.xml.SourceHttpMessageConverter;
import org.springframework.ui.ModelMap;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ReflectionUtils.MethodFilter;
import org.springframework.web.accept.ContentNegotiationManager;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.support.DefaultDataBinderFactory;
import org.springframework.web.bind.support.DefaultSessionAttributeStore;
import org.springframework.web.bind.support.SessionAttributeStore;
import org.springframework.web.bind.support.WebBindingInitializer;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.context.request.async.AsyncWebRequest;
import org.springframework.web.context.request.async.CallableProcessingInterceptor;
import org.springframework.web.context.request.async.DeferredResultProcessingInterceptor;
import org.springframework.web.context.request.async.WebAsyncManager;
import org.springframework.web.context.request.async.WebAsyncTask;
import org.springframework.web.context.request.async.WebAsyncUtils;
import org.springframework.web.method.ControllerAdviceBean;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.method.annotation.ErrorsMethodArgumentResolver;
import org.springframework.web.method.annotation.ExpressionValueMethodArgumentResolver;
import org.springframework.web.method.annotation.InitBinderDataBinderFactory;
import org.springframework.web.method.annotation.MapMethodProcessor;
import org.springframework.web.method.annotation.ModelAttributeMethodProcessor;
import org.springframework.web.method.annotation.ModelFactory;
import org.springframework.web.method.annotation.ModelMethodProcessor;
import org.springframework.web.method.annotation.RequestHeaderMapMethodArgumentResolver;
import org.springframework.web.method.annotation.RequestHeaderMethodArgumentResolver;
import org.springframework.web.method.annotation.RequestParamMapMethodArgumentResolver;
import org.springframework.web.method.annotation.RequestParamMethodArgumentResolver;
import org.springframework.web.method.annotation.SessionAttributesHandler;
import org.springframework.web.method.annotation.SessionStatusMethodArgumentResolver;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.HandlerMethodArgumentResolverComposite;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite;
import org.springframework.web.method.support.InvocableHandlerMethod;
import org.springframework.web.method.support.ModelAndViewContainer;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.mvc.annotation.ModelAndViewResolver;
import org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import org.springframework.web.servlet.support.RequestContextUtils;
import org.springframework.web.util.WebUtils;

/**
 * An {@link AbstractHandlerMethodAdapter} that supports {@link HandlerMethod}s
 * with their method argument and return type signature, as defined via
 * {@code @RequestMapping}.
 *
 * <p>Support for custom argument and return value types can be added via
 * {@link #setCustomArgumentResolvers} and {@link #setCustomReturnValueHandlers}.
 * Or alternatively, to re-configure all argument and return value types,
 * use {@link #setArgumentResolvers} and {@link #setReturnValueHandlers}.
 *
 * @author Rossen Stoyanchev
 * @author Juergen Hoeller
 * @author Sam Brannen
 * @since 3.1
 * @see HandlerMethodArgumentResolver
 * @see HandlerMethodReturnValueHandler
 */
public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter implements BeanFactoryAware, InitializingBean {

	/**
	 * MethodFilter that matches {@link InitBinder @InitBinder} methods.
	 */
	public static final MethodFilter INIT_BINDER_METHODS = new MethodFilter() {
		@Override
		public boolean matches(Method method) {
			return (AnnotationUtils.findAnnotation(method, InitBinder.class) != null);
		}
	};

	/**
	 * MethodFilter that matches {@link ModelAttribute @ModelAttribute} methods.
	 */
	public static final MethodFilter MODEL_ATTRIBUTE_METHODS = new MethodFilter() {
		@Override
		public boolean matches(Method method) {
			return (AnnotationUtils.findAnnotation(method, RequestMapping.class) == null &&
					AnnotationUtils.findAnnotation(method, ModelAttribute.class) != null);
		}
	};


	private List<HandlerMethodArgumentResolver> customArgumentResolvers;

	private HandlerMethodArgumentResolverComposite argumentResolvers;

	private HandlerMethodArgumentResolverComposite initBinderArgumentResolvers;

	private List<HandlerMethodReturnValueHandler> customReturnValueHandlers;

	private HandlerMethodReturnValueHandlerComposite returnValueHandlers;

	private List<ModelAndViewResolver> modelAndViewResolvers;

	private ContentNegotiationManager contentNegotiationManager = new ContentNegotiationManager();

	private List<HttpMessageConverter<?>> messageConverters;

	private List<Object> requestResponseBodyAdvice = new ArrayList<Object>();

	private WebBindingInitializer webBindingInitializer;

	private AsyncTaskExecutor taskExecutor = new SimpleAsyncTaskExecutor("MvcAsync");

	private Long asyncRequestTimeout;

	private CallableProcessingInterceptor[] callableInterceptors = new CallableProcessingInterceptor[0];

	private DeferredResultProcessingInterceptor[] deferredResultInterceptors = new DeferredResultProcessingInterceptor[0];

	private boolean ignoreDefaultModelOnRedirect = false;

	private int cacheSecondsForSessionAttributeHandlers = 0;

	private boolean synchronizeOnSession = false;

	private SessionAttributeStore sessionAttributeStore = new DefaultSessionAttributeStore();

	private ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();

	private ConfigurableBeanFactory beanFactory;


	private final Map<Class<?>, SessionAttributesHandler> sessionAttributesHandlerCache =
			new ConcurrentHashMap<Class<?>, SessionAttributesHandler>(64);

	private final Map<Class<?>, Set<Method>> initBinderCache = new ConcurrentHashMap<Class<?>, Set<Method>>(64);

	private final Map<ControllerAdviceBean, Set<Method>> initBinderAdviceCache =
			new LinkedHashMap<ControllerAdviceBean, Set<Method>>();

	private final Map<Class<?>, Set<Method>> modelAttributeCache = new ConcurrentHashMap<Class<?>, Set<Method>>(64);

	private final Map<ControllerAdviceBean, Set<Method>> modelAttributeAdviceCache =
			new LinkedHashMap<ControllerAdviceBean, Set<Method>>();


	public RequestMappingHandlerAdapter() {
		// 创建String类型的消息转换器
		StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter();
		// 设置此消息转换器不向响应中写入Accept-Charset响应头，默认为true
		stringHttpMessageConverter.setWriteAcceptCharset(false);  // see SPR-7316
		// 为本类的消息转换器列表属性创建实例
		this.messageConverters = new ArrayList<HttpMessageConverter<?>>(4);
		// 添加byte数组类型的消息转换器
		this.messageConverters.add(new ByteArrayHttpMessageConverter());
		// 把刚才创建的String类型消息转换器添加到list中
		this.messageConverters.add(stringHttpMessageConverter);
		// 添加一个source类型的消息转换器，用于转换spring提供的Source类型的转换
		this.messageConverters.add(new SourceHttpMessageConverter<Source>());
		// 添加一个包含全部消息转换器的消息转换器，用于对表单数据进行转换，如xml和json转换器
		this.messageConverters.add(new AllEncompassingFormHttpMessageConverter());
		// 这里添加的messageConverters会在adapter.setMessageConverters(getMessageConverters());被替换掉
	}


	/**
	 * Provide resolvers for custom argument types. Custom resolvers are ordered
	 * after built-in ones. To override the built-in support for argument
	 * resolution use {@link #setArgumentResolvers} instead.
	 */
	public void setCustomArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
		this.customArgumentResolvers = argumentResolvers;
	}

	/**
	 * Return the custom argument resolvers, or {@code null}.
	 */
	public List<HandlerMethodArgumentResolver> getCustomArgumentResolvers() {
		return this.customArgumentResolvers;
	}

	/**
	 * Configure the complete list of supported argument types thus overriding
	 * the resolvers that would otherwise be configured by default.
	 */
	public void setArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
		if (argumentResolvers == null) {
			this.argumentResolvers = null;
		}
		else {
			this.argumentResolvers = new HandlerMethodArgumentResolverComposite();
			this.argumentResolvers.addResolvers(argumentResolvers);
		}
	}

	/**
	 * Return the configured argument resolvers, or possibly {@code null} if
	 * not initialized yet via {@link #afterPropertiesSet()}.
	 */
	public List<HandlerMethodArgumentResolver> getArgumentResolvers() {
		return (this.argumentResolvers != null ? this.argumentResolvers.getResolvers() : null);
	}

	/**
	 * Configure the supported argument types in {@code @InitBinder} methods.
	 */
	public void setInitBinderArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
		if (argumentResolvers == null) {
			this.initBinderArgumentResolvers = null;
		}
		else {
			this.initBinderArgumentResolvers = new HandlerMethodArgumentResolverComposite();
			this.initBinderArgumentResolvers.addResolvers(argumentResolvers);
		}
	}

	/**
	 * Return the argument resolvers for {@code @InitBinder} methods, or possibly
	 * {@code null} if not initialized yet via {@link #afterPropertiesSet()}.
	 */
	public List<HandlerMethodArgumentResolver> getInitBinderArgumentResolvers() {
		return (this.initBinderArgumentResolvers != null ? this.initBinderArgumentResolvers.getResolvers() : null);
	}

	/**
	 * Provide handlers for custom return value types. Custom handlers are
	 * ordered after built-in ones. To override the built-in support for
	 * return value handling use {@link #setReturnValueHandlers}.
	 */
	public void setCustomReturnValueHandlers(List<HandlerMethodReturnValueHandler> returnValueHandlers) {
		this.customReturnValueHandlers = returnValueHandlers;
	}

	/**
	 * Return the custom return value handlers, or {@code null}.
	 */
	public List<HandlerMethodReturnValueHandler> getCustomReturnValueHandlers() {
		return this.customReturnValueHandlers;
	}

	/**
	 * Configure the complete list of supported return value types thus
	 * overriding handlers that would otherwise be configured by default.
	 */
	public void setReturnValueHandlers(List<HandlerMethodReturnValueHandler> returnValueHandlers) {
		if (returnValueHandlers == null) {
			this.returnValueHandlers = null;
		}
		else {
			this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite();
			this.returnValueHandlers.addHandlers(returnValueHandlers);
		}
	}

	/**
	 * Return the configured handlers, or possibly {@code null} if not
	 * initialized yet via {@link #afterPropertiesSet()}.
	 */
	public List<HandlerMethodReturnValueHandler> getReturnValueHandlers() {
		return (this.returnValueHandlers != null ? this.returnValueHandlers.getHandlers() : null);
	}

	/**
	 * Provide custom {@link ModelAndViewResolver}s.
	 * <p><strong>Note:</strong> This method is available for backwards
	 * compatibility only. However, it is recommended to re-write a
	 * {@code ModelAndViewResolver} as {@link HandlerMethodReturnValueHandler}.
	 * An adapter between the two interfaces is not possible since the
	 * {@link HandlerMethodReturnValueHandler#supportsReturnType} method
	 * cannot be implemented. Hence {@code ModelAndViewResolver}s are limited
	 * to always being invoked at the end after all other return value
	 * handlers have been given a chance.
	 * <p>A {@code HandlerMethodReturnValueHandler} provides better access to
	 * the return type and controller method information and can be ordered
	 * freely relative to other return value handlers.
	 */
	public void setModelAndViewResolvers(List<ModelAndViewResolver> modelAndViewResolvers) {
		this.modelAndViewResolvers = modelAndViewResolvers;
	}

	/**
	 * Return the configured {@link ModelAndViewResolver}s, or {@code null}.
	 */
	public List<ModelAndViewResolver> getModelAndViewResolvers() {
		return this.modelAndViewResolvers;
	}

	/**
	 * Set the {@link ContentNegotiationManager} to use to determine requested media types.
	 * If not set, the default constructor is used.
	 */
	public void setContentNegotiationManager(ContentNegotiationManager contentNegotiationManager) {
		this.contentNegotiationManager = contentNegotiationManager;
	}

	/**
	 * Provide the converters to use in argument resolvers and return value
	 * handlers that support reading and/or writing to the body of the
	 * request and response.
	 */
	public void setMessageConverters(List<HttpMessageConverter<?>> messageConverters) {
		this.messageConverters = messageConverters;
	}

	/**
	 * Return the configured message body converters.
	 */
	public List<HttpMessageConverter<?>> getMessageConverters() {
		return this.messageConverters;
	}

	/**
	 * Add one or more {@code RequestBodyAdvice} instances to intercept the
	 * request before it is read and converted for {@code @RequestBody} and
	 * {@code HttpEntity} method arguments.
	 */
	public void setRequestBodyAdvice(List<RequestBodyAdvice> requestBodyAdvice) {
		if (requestBodyAdvice != null) {
			this.requestResponseBodyAdvice.addAll(requestBodyAdvice);
		}
	}

	/**
	 * Add one or more {@code ResponseBodyAdvice} instances to intercept the
	 * response before {@code @ResponseBody} or {@code ResponseEntity} return
	 * values are written to the response body.
	 */
	public void setResponseBodyAdvice(List<ResponseBodyAdvice<?>> responseBodyAdvice) {
		if (responseBodyAdvice != null) {
			this.requestResponseBodyAdvice.addAll(responseBodyAdvice);
		}
	}

	/**
	 * Provide a WebBindingInitializer with "global" initialization to apply
	 * to every DataBinder instance.
	 */
	public void setWebBindingInitializer(WebBindingInitializer webBindingInitializer) {
		this.webBindingInitializer = webBindingInitializer;
	}

	/**
	 * Return the configured WebBindingInitializer, or {@code null} if none.
	 */
	public WebBindingInitializer getWebBindingInitializer() {
		return this.webBindingInitializer;
	}

	/**
	 * Set the default {@link AsyncTaskExecutor} to use when a controller method
	 * return a {@link Callable}. Controller methods can override this default on
	 * a per-request basis by returning an {@link WebAsyncTask}.
	 * <p>By default a {@link SimpleAsyncTaskExecutor} instance is used.
	 * It's recommended to change that default in production as the simple executor
	 * does not re-use threads.
	 */
	public void setTaskExecutor(AsyncTaskExecutor taskExecutor) {
		this.taskExecutor = taskExecutor;
	}

	/**
	 * Specify the amount of time, in milliseconds, before concurrent handling
	 * should time out. In Servlet 3, the timeout begins after the main request
	 * processing thread has exited and ends when the request is dispatched again
	 * for further processing of the concurrently produced result.
	 * <p>If this value is not set, the default timeout of the underlying
	 * implementation is used, e.g. 10 seconds on Tomcat with Servlet 3.
	 * @param timeout the timeout value in milliseconds
	 */
	public void setAsyncRequestTimeout(long timeout) {
		this.asyncRequestTimeout = timeout;
	}

	/**
	 * Configure {@code CallableProcessingInterceptor}'s to register on async requests.
	 * @param interceptors the interceptors to register
	 */
	public void setCallableInterceptors(List<CallableProcessingInterceptor> interceptors) {
		Assert.notNull(interceptors, "CallableProcessingInterceptor List must not be null");
		this.callableInterceptors = interceptors.toArray(new CallableProcessingInterceptor[interceptors.size()]);
	}

	/**
	 * Configure {@code DeferredResultProcessingInterceptor}'s to register on async requests.
	 * @param interceptors the interceptors to register
	 */
	public void setDeferredResultInterceptors(List<DeferredResultProcessingInterceptor> interceptors) {
		Assert.notNull(interceptors, "DeferredResultProcessingInterceptor List must not be null");
		this.deferredResultInterceptors = interceptors.toArray(new DeferredResultProcessingInterceptor[interceptors.size()]);
	}

	/**
	 * By default the content of the "default" model is used both during
	 * rendering and redirect scenarios. Alternatively a controller method
	 * can declare a {@link RedirectAttributes} argument and use it to provide
	 * attributes for a redirect.
	 * <p>Setting this flag to {@code true} guarantees the "default" model is
	 * never used in a redirect scenario even if a RedirectAttributes argument
	 * is not declared. Setting it to {@code false} means the "default" model
	 * may be used in a redirect if the controller method doesn't declare a
	 * RedirectAttributes argument.
	 * <p>The default setting is {@code false} but new applications should
	 * consider setting it to {@code true}.
	 * @see RedirectAttributes
	 */
	public void setIgnoreDefaultModelOnRedirect(boolean ignoreDefaultModelOnRedirect) {
		this.ignoreDefaultModelOnRedirect = ignoreDefaultModelOnRedirect;
	}

	/**
	 * Specify the strategy to store session attributes with. The default is
	 * {@link org.springframework.web.bind.support.DefaultSessionAttributeStore},
	 * storing session attributes in the HttpSession with the same attribute
	 * name as in the model.
	 */
	public void setSessionAttributeStore(SessionAttributeStore sessionAttributeStore) {
		this.sessionAttributeStore = sessionAttributeStore;
	}

	/**
	 * Cache content produced by {@code @SessionAttributes} annotated handlers
	 * for the given number of seconds.
	 * <p>Possible values are:
	 * <ul>
	 * <li>-1: no generation of cache-related headers</li>
	 * <li>0 (default value): "Cache-Control: no-store" will prevent caching</li>
	 * <li>1 or higher: "Cache-Control: max-age=seconds" will ask to cache content;
	 * not advised when dealing with session attributes</li>
	 * </ul>
	 * <p>In contrast to the "cacheSeconds" property which will apply to all general
	 * handlers (but not to {@code @SessionAttributes} annotated handlers),
	 * this setting will apply to {@code @SessionAttributes} handlers only.
	 * @see #setCacheSeconds
	 * @see org.springframework.web.bind.annotation.SessionAttributes
	 */
	public void setCacheSecondsForSessionAttributeHandlers(int cacheSecondsForSessionAttributeHandlers) {
		this.cacheSecondsForSessionAttributeHandlers = cacheSecondsForSessionAttributeHandlers;
	}

	/**
	 * Set if controller execution should be synchronized on the session,
	 * to serialize parallel invocations from the same client.
	 * <p>More specifically, the execution of the {@code handleRequestInternal}
	 * method will get synchronized if this flag is "true". The best available
	 * session mutex will be used for the synchronization; ideally, this will
	 * be a mutex exposed by HttpSessionMutexListener.
	 * <p>The session mutex is guaranteed to be the same object during
	 * the entire lifetime of the session, available under the key defined
	 * by the {@code SESSION_MUTEX_ATTRIBUTE} constant. It serves as a
	 * safe reference to synchronize on for locking on the current session.
	 * <p>In many cases, the HttpSession reference itself is a safe mutex
	 * as well, since it will always be the same object reference for the
	 * same active logical session. However, this is not guaranteed across
	 * different servlet containers; the only 100% safe way is a session mutex.
	 * @see org.springframework.web.util.HttpSessionMutexListener
	 * @see org.springframework.web.util.WebUtils#getSessionMutex(javax.servlet.http.HttpSession)
	 */
	public void setSynchronizeOnSession(boolean synchronizeOnSession) {
		this.synchronizeOnSession = synchronizeOnSession;
	}

	/**
	 * Set the ParameterNameDiscoverer to use for resolving method parameter names if needed
	 * (e.g. for default attribute names).
	 * <p>Default is a {@link org.springframework.core.DefaultParameterNameDiscoverer}.
	 */
	public void setParameterNameDiscoverer(ParameterNameDiscoverer parameterNameDiscoverer) {
		this.parameterNameDiscoverer = parameterNameDiscoverer;
	}

	/**
	 * A {@link ConfigurableBeanFactory} is expected for resolving expressions
	 * in method argument default values.
	 */
	@Override
	public void setBeanFactory(BeanFactory beanFactory) {
		if (beanFactory instanceof ConfigurableBeanFactory) {
			this.beanFactory = (ConfigurableBeanFactory) beanFactory;
		}
	}

	/**
	 * Return the owning factory of this bean instance, or {@code null} if none.
	 */
	protected ConfigurableBeanFactory getBeanFactory() {
		return this.beanFactory;
	}


	@Override
	public void afterPropertiesSet() {
		// Do this first, it may add ResponseBody advice beans
		// 初始化ControllerAdvice缓存，即初始化@ControllerAdvice标记的处理器增强相关缓存
		initControllerAdviceCache();

		// 如果此时本实例的参数解析器为空，则执行参数解析器初始化逻辑
		// 因为在bean定义中并没有设置参数解析器的值，只是设置了自定义参数解析器customArgumentResolvers的值，所以这里进入初始化逻辑
		if (this.argumentResolvers == null) {
			// 获取默认的方法参数解析器
			List<HandlerMethodArgumentResolver> resolvers = getDefaultArgumentResolvers();
			// 把全部参数解析器封装为参数解析器复合类，作为本类的参数解析器组件使用
			this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
		}
		// 如果InitBinder得到参数解析器为空(默认为空)
		if (this.initBinderArgumentResolvers == null) {
			// 获取默认的@InitBinder参数绑定解析器，该注解标记的方法也可以提供多个参数，而这些参数的解析逻辑与处理器方法上的参数解析逻辑略有不同，不需要太多组件即可
			List<HandlerMethodArgumentResolver> resolvers = getDefaultInitBinderArgumentResolvers();
			// 封装为参数解析器复合类，作为本实例的InitBinder参数解析器组件使用
			this.initBinderArgumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
		}
		// 如果返回值处理器为空(默认为空)
		if (this.returnValueHandlers == null) {
			// 获取默认返回值处理器列表
			List<HandlerMethodReturnValueHandler> handlers = getDefaultReturnValueHandlers();
			// 封装为复合返回值处理器，作为本类的返回值处理器组件使用
			this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers);
		}
	}

	private void initControllerAdviceCache() {
		// 应用上下文为null，不做初始化处理
		if (getApplicationContext() == null) {
			return;
		}
		if (logger.isInfoEnabled()) {
			logger.info("Looking for @ControllerAdvice: " + getApplicationContext());
		}
		// 从beanFactory中获取参数@ControllerAdvice的controller
		List<ControllerAdviceBean> beans = ControllerAdviceBean.findAnnotatedBeans(getApplicationContext());
		// 使用bean排序逻辑对列表进行排序
		AnnotationAwareOrderComparator.sort(beans);
		// 请求响应body增强器bean列表
		List<Object> requestResponseBodyAdviceBeans = new ArrayList<Object>();

		for (ControllerAdviceBean bean : beans) {
			// 获取相应的bean类型
			Class<?> beanType = bean.getBeanType();
			// 查找处理器增强bean中被@ModelAttribute标记但未被@RequestMapping标记的方法
			Set<Method> attrMethods = MethodIntrospector.selectMethods(beanType, MODEL_ATTRIBUTE_METHODS);
			if (!attrMethods.isEmpty()) {
				// 如果不为空，则添加到modelAttributeAdviceCache增强缓存中
				this.modelAttributeAdviceCache.put(bean, attrMethods);
				if (logger.isInfoEnabled()) {
					logger.info("Detected @ModelAttribute methods in " + bean);
				}
			}
			// 查找处理器增强bean中被@InitBinder标记的方法
			Set<Method> binderMethods = MethodIntrospector.selectMethods(beanType, INIT_BINDER_METHODS);
			if (!binderMethods.isEmpty()) {
				// 如果不为空，则添加到initBinderAdviceCache增强缓存中
				this.initBinderAdviceCache.put(bean, binderMethods);
				if (logger.isInfoEnabled()) {
					logger.info("Detected @InitBinder methods in " + bean);
				}
			}

			boolean isRequestBodyAdvice = RequestBodyAdvice.class.isAssignableFrom(beanType);
			boolean isResponseBodyAdvice = ResponseBodyAdvice.class.isAssignableFrom(beanType);
			if (isRequestBodyAdvice || isResponseBodyAdvice) {
				requestResponseBodyAdviceBeans.add(bean);
				if (logger.isInfoEnabled()) {
					if (isRequestBodyAdvice) {
						logger.info("Detected RequestBodyAdvice bean in " + bean);
					}
					else {
						logger.info("Detected ResponseBodyAdvice bean in " + bean);
					}
				}
			}
		}

		if (!requestResponseBodyAdviceBeans.isEmpty()) {
			this.requestResponseBodyAdvice.addAll(0, requestResponseBodyAdviceBeans);
		}
	}

	/**
	 * Return the list of argument resolvers to use including built-in resolvers
	 * and custom resolvers provided via {@link #setCustomArgumentResolvers}.
	 */
	private List<HandlerMethodArgumentResolver> getDefaultArgumentResolvers() {
		List<HandlerMethodArgumentResolver> resolvers = new ArrayList<HandlerMethodArgumentResolver>();

		// 基于@RequestParam注解的基本类型参数解析器
		resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), false));
		// 基于@RequestParam注解的map类型参数解析器
		resolvers.add(new RequestParamMapMethodArgumentResolver());
		// 基于@PathVariable注解的基本类型参数解析器
		resolvers.add(new PathVariableMethodArgumentResolver());
		// 基于@PathVariable注解的map类型参数解析器
		resolvers.add(new PathVariableMapMethodArgumentResolver());
		// 基于@MatrixVariable注解的基本类型参数解析器
		resolvers.add(new MatrixVariableMethodArgumentResolver());
		// 基于@MatrixVariable注解的map类型参数解析器
		resolvers.add(new MatrixVariableMapMethodArgumentResolver());
		// 基于@ModelAttribute注解的参数解析器
		resolvers.add(new ServletModelAttributeMethodProcessor(false));
		// 基于@RequestBody、@ResponseBody的参数解析器，传入了所有的消息转换器，供内部使用
		resolvers.add(new RequestResponseBodyMethodProcessor(getMessageConverters(), this.requestResponseBodyAdvice));
		// 基于@RequestPart注解的参数解析器，传入了所有的消息转换器，供内部使用
		resolvers.add(new RequestPartMethodArgumentResolver(getMessageConverters(), this.requestResponseBodyAdvice));
		// 基于@RequestHeader注解的基本类型参数解析器
		resolvers.add(new RequestHeaderMethodArgumentResolver(getBeanFactory()));
		// 基于@RequestHeader注解的map类型参数解析器
		resolvers.add(new RequestHeaderMapMethodArgumentResolver());
		// @CookieValue注解的参数解析器
		resolvers.add(new ServletCookieValueMethodArgumentResolver(getBeanFactory()));
		// 基于@Value表达式参数解析器
		resolvers.add(new ExpressionValueMethodArgumentResolver(getBeanFactory()));
		// 基于@SessionAttribute注解的参数解析器
		resolvers.add(new SessionAttributeMethodArgumentResolver());
		// 基于@RequestAttribute注解的参数解析器
		resolvers.add(new RequestAttributeMethodArgumentResolver());

		// 基于参数类型的参数解析器，顺序在注解参数解析器后面
		// 基于servletRequest的参数解析器
		resolvers.add(new ServletRequestMethodArgumentResolver());
		// 基于servletResponse的参数解析器
		resolvers.add(new ServletResponseMethodArgumentResolver());
		// 基于httpEntity参数解析器，传入了所有的消息转换器，供内部使用
		resolvers.add(new HttpEntityMethodProcessor(getMessageConverters(), this.requestResponseBodyAdvice));
		// 基于重定向(RedirectAttributes类型)参数绑定解析器
		resolvers.add(new RedirectAttributesMethodArgumentResolver());
		// Model类型的参数解析器
		resolvers.add(new ModelMethodProcessor());
		// Map类型的参数解析器
		resolvers.add(new MapMethodProcessor());
		// Errors类型的参数解析器
		resolvers.add(new ErrorsMethodArgumentResolver());
		// SessionStatus类型的参数解析器
		resolvers.add(new SessionStatusMethodArgumentResolver());
		// UriComponentsBuilder和ServletUriComponentsBuilder类型的参数解析器
		resolvers.add(new UriComponentsBuilderMethodArgumentResolver());

		// 自定义参数解析器，通过bean定义时传入，添加到后面
		if (getCustomArgumentResolvers() != null) {
			resolvers.addAll(getCustomArgumentResolvers());
		}

		// 请求参数解析器，无需显式声明注解，参数类型是简单类型时进入此解析器逻辑
		resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), true));
		// 模型属性解析器，无需显式声明注解，参数类型不是简单类型时进入此解析器逻辑，覆盖全部类型
		resolvers.add(new ServletModelAttributeMethodProcessor(true));

		return resolvers;
	}

	/**
	 * Return the list of argument resolvers to use for {@code @InitBinder}
	 * methods including built-in and custom resolvers.
	 */
	private List<HandlerMethodArgumentResolver> getDefaultInitBinderArgumentResolvers() {
		List<HandlerMethodArgumentResolver> resolvers = new ArrayList<HandlerMethodArgumentResolver>();

		// 基于@RequestParam注解的基本类型参数解析器
		resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), false));
		// 基于@RequestParam注解的map类型参数解析器
		resolvers.add(new RequestParamMapMethodArgumentResolver());
		// 基于@PathVariable注解的基本类型参数解析器
		resolvers.add(new PathVariableMethodArgumentResolver());
		// 基于@PathVariable注解的map类型参数解析器
		resolvers.add(new PathVariableMapMethodArgumentResolver());
		// 基于@MatrixVariable注解的基本类型参数解析器
		resolvers.add(new MatrixVariableMethodArgumentResolver());
		// 基于@MatrixVariable注解的map类型参数解析器
		resolvers.add(new MatrixVariableMapMethodArgumentResolver());
		// 基于@Value表达式参数解析器
		resolvers.add(new ExpressionValueMethodArgumentResolver(getBeanFactory()));
		// 基于@SessionAttribute注解的参数解析器
		resolvers.add(new SessionAttributeMethodArgumentResolver());
		// 基于@RequestAttribute注解的参数解析器
		resolvers.add(new RequestAttributeMethodArgumentResolver());

		// 基于参数类型的参数解析器，顺序在注解参数解析器后面
		// 基于servletRequest的参数解析器
		resolvers.add(new ServletRequestMethodArgumentResolver());
		// 基于servletResponse的参数解析器
		resolvers.add(new ServletResponseMethodArgumentResolver());

		// 自定义参数解析器，通过bean定义时传入，添加到后面
		if (getCustomArgumentResolvers() != null) {
			resolvers.addAll(getCustomArgumentResolvers());
		}

		// 请求参数解析器，无需显式声明注解，参数类型是简单类型时进入此解析器逻辑
		resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), true));

		return resolvers;
	}

	/**
	 * Return the list of return value handlers to use including built-in and
	 * custom handlers provided via {@link #setReturnValueHandlers}.
	 */
	private List<HandlerMethodReturnValueHandler> getDefaultReturnValueHandlers() {
		// 声明用于保存结果的list
		List<HandlerMethodReturnValueHandler> handlers = new ArrayList<HandlerMethodReturnValueHandler>();

		// 单个功能返回值类型的处理器支持
		// 用于支持ModelAndView类型的返回值
		handlers.add(new ModelAndViewMethodReturnValueHandler());
		// 用于支持Model类型的返回值
		handlers.add(new ModelMethodProcessor());
		// 用于支持View类型的返回值
		handlers.add(new ViewMethodReturnValueHandler());
		// 用于支持ResponseBodyEmitter类型和Reactive类型的返回值，传入消息转换器列表与内容协商管理器供内部使用
		handlers.add(new ResponseBodyEmitterReturnValueHandler(getMessageConverters()));
		// 用于支持StreamingResponseBody类型的返回值
		handlers.add(new StreamingResponseBodyReturnValueHandler());
		// 用于支持HttpEntity与ResponseEntity类型的返回值
		handlers.add(new HttpEntityMethodProcessor(getMessageConverters(), this.contentNegotiationManager, this.requestResponseBodyAdvice));
		// 用于支持HttpHeaders类型的返回值
		handlers.add(new HttpHeadersReturnValueHandler());
		// 用于支持异步响应结果Callable类型的返回值
		handlers.add(new CallableMethodReturnValueHandler());
		// 用于支持异步响应结果DeferredResult、ListenableFuture、CompletionStage类型的返回值
		handlers.add(new DeferredResultMethodReturnValueHandler());
		// 用于支持异步响应结果WebAsyncTask类型的返回值
		handlers.add(new AsyncTaskMethodReturnValueHandler(this.beanFactory));

		// 基于注解的返回值处理，与参数解析器的顺序相反
		// 用于对@ModelAttribute标记方法的返回值进行处理
		handlers.add(new ModelAttributeMethodProcessor(false));
		// 用于对@RequestBody、@ResponseBody标记方法的返回值进行处理
		handlers.add(new RequestResponseBodyMethodProcessor(getMessageConverters(), this.contentNegotiationManager, this.requestResponseBodyAdvice));

		// 多个目的的返回值处理器
		// 对String类型返回值进行处理，视图名返回值处理器返回String均视为视图名
		handlers.add(new ViewNameMethodReturnValueHandler());
		// 提供Map类型的返回值处理功能
		handlers.add(new MapMethodProcessor());

		// 自定义的返回值处理器，放在前面明确的返回值处理器之后
		if (getCustomReturnValueHandlers() != null) {
			handlers.addAll(getCustomReturnValueHandlers());
		}

		// 最后添加一个用于处理全部返回值的处理器
		if (!CollectionUtils.isEmpty(getModelAndViewResolvers())) {
			// 如果modelAndViewResolvers不为空，则创建一个使用该解析器返回ModelAndView类型结果的返回值处理器，此时处理器方法无需返回值
			handlers.add(new ModelAndViewResolverMethodReturnValueHandler(getModelAndViewResolvers()));
		}
		else {
			// 否则，在没有这个解析器组件时，创建一个无需显式声明的@ModelAttribute
			handlers.add(new ModelAttributeMethodProcessor(true));
		}

		return handlers;
	}


	/**
	 * Always return {@code true} since any method argument and return value
	 * type will be processed in some way. A method argument not recognized
	 * by any HandlerMethodArgumentResolver is interpreted as a request parameter
	 * if it is a simple type, or as a model attribute otherwise. A return value
	 * not recognized by any HandlerMethodReturnValueHandler will be interpreted
	 * as a model attribute.
	 */
	@Override
	protected boolean supportsInternal(HandlerMethod handlerMethod) {
		// 这里RequestMappingHandlerAdapter只是对supportsInternal()返回true，因为其只需要处理的handler类型是HandlerMethod类型即可
		return true;
	}

	// 主要做了两部分处理：①判断当前是否对session进行同步处理，如果需要，则对其调用进行加锁，不需要则直接调用；②判断请求头中是否包含Cache-Control请求头，如果不包含，则设置其Cache立即失效。可以看到，对于HandlerMethod的具体处理是在invokeHandlerMethod()方法中进行的
	@Override
	protected ModelAndView handleInternal(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
		// 先声明ModelAndView结果
		ModelAndView mav;
		// 检查请求是否被支持，包含两个逻辑：1、判断本实例中的supportedMethods是否包含请求方法，默认支持所有请求方法；2、如果配置的需要session属性为true，检查请求是否包含session，默认不需要session
		checkRequest(request);

		// 判断当前是否需要支持在同一个session中只能线性地处理请求
		if (this.synchronizeOnSession) {
			// 获取当前请求的session对象
			HttpSession session = request.getSession(false);
			if (session != null) {
				// 为当前session生成一个唯一的可以用于锁定的key
				Object mutex = WebUtils.getSessionMutex(session);
				synchronized (mutex) {
					// 加锁后，对HandlerMethod进行参数等的适配处理，并调用目标handler
					mav = invokeHandlerMethod(request, response, handlerMethod);
				}
			}
			else {
				// 如果当前不存在session，则直接对HandlerMethod进行适配
				mav = invokeHandlerMethod(request, response, handlerMethod);
			}
		}
		else {
			// 如果当前不需要对session进行同步处理，则直接对HandlerMethod进行适配
			mav = invokeHandlerMethod(request, response, handlerMethod);
		}

		// 判断当前响应结果中是否包含Cache-Control控制头，如果不包含，则对当前response进行处理，为其设置过期时间
		if (!response.containsHeader(HEADER_CACHE_CONTROL)) {
			// 如果当前SessionAttribute中存在配置的attributes，则为其设置过期时间。这里SessionAttribute主要是通过@SessionAttribute注解生成的
			if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
				// 应用SessionAttribute的缓存策略，默认cacheSecondsForSessionAttributeHandlers为0，表示不缓存
				applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
			}
			else {
				// 如果当前不存在SessionAttributes，则判断当前是否存在Cache-Control设置，
	            // 如果存在，则按照该设置进行response处理，如果不存在，则设置response中的Cache的过期时间为-1，即立即失效
				// 本适配器默认没有缓存策略，故所有请求都不返回缓存响应头
				prepareResponse(response);
			}
		}

		return mav;
	}

	/**
	 * This implementation always returns -1. An {@code @RequestMapping} method can
	 * calculate the lastModified value, call {@link WebRequest#checkNotModified(long)},
	 * and return {@code null} if the result of that call is {@code true}.
	 */
	@Override
	protected long getLastModifiedInternal(HttpServletRequest request, HandlerMethod handlerMethod) {
		// 表示所有的HandlerMethod都不支持http缓存
		return -1;
	}


	/**
	 * Return the {@link SessionAttributesHandler} instance for the given handler type
	 * (never {@code null}).
	 */
	private SessionAttributesHandler getSessionAttributesHandler(HandlerMethod handlerMethod) {
		Class<?> handlerType = handlerMethod.getBeanType();
		SessionAttributesHandler sessionAttrHandler = this.sessionAttributesHandlerCache.get(handlerType);
		if (sessionAttrHandler == null) {
			synchronized (this.sessionAttributesHandlerCache) {
				sessionAttrHandler = this.sessionAttributesHandlerCache.get(handlerType);
				if (sessionAttrHandler == null) {
					sessionAttrHandler = new SessionAttributesHandler(handlerType, sessionAttributeStore);
					this.sessionAttributesHandlerCache.put(handlerType, sessionAttrHandler);
				}
			}
		}
		return sessionAttrHandler;
	}

	/**主要包含四个部分：
	 * <br/>①获取当前容器中使用@InitBinder注解注册的属性转换器；
	 * <br/>②获取当前容器中使用@ModelAttribute标注但没有使用@RequestMapping标注的方法，并且在调用目标方法之前调用这些方法；
	 * <br/>③判断目标handler返回值是否使用了WebAsyncTask或DefferredResult封装，如果封装了，则按照异步任务的方式进行执行；
	 * <br/>④处理请求参数，调用目标方法和处理返回值。
	 * <br/>Invoke the {@link RequestMapping} handler method preparing a {@link ModelAndView}
	 * if view resolution is required.
	 * @since 4.2
	 * @see #createInvocableHandlerMethod(HandlerMethod)
	 */
	protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
		// 把请求与响应封装为一个ServletWebRequest对象，用于后续处理逻辑使用
		ServletWebRequest webRequest = new ServletWebRequest(request, response);
		try {
			// 获取容器中全局配置的InitBinder和当前HandlerMethod所对应的Controller中配置的InitBinder，用于进行参数的绑定
			WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
			// 获取容器中全局配置的ModelAttribute和当前HandlerMethod所对应的Controller中配置的ModelAttribute，这些配置的方法将会在目标方法调用之前进行调用
			ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);

			// 将handlerMethod封装为一个ServletInvocableHandlerMethod对象，该对象用于对当前request的整体调用流程进行了封装
			ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
			// 设置invocableMethod的参数解析器为当前组件初始化后的参数解析器
			invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
			// 设置invocableMethod的返回值处理器为当前组件初始化后的返回值处理器
			invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
			// 将前面创建的WebDataBinderFactory设置到ServletInvocableHandlerMethod中
			invocableMethod.setDataBinderFactory(binderFactory);
			// 设置ParameterNameDiscoverer，该对象将按照一定的规则获取当前参数的名称
			invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);
			// 需要返回值处理器是因为处理器方法的返回值需要被处理后才能被应用到响应中
			// 以上初始化可调用处理器方法实例中，并没有使用Model工厂，而且各个初始化方法也未被调用，仅仅是生成一个待调用的可调用处理器方法实例，其真实性调用在后面

			// 最后返回的结果类型为ModelAndView，而在整个处理器方法调用流程中，随时可能对这个结果做修改，所以这里先创建ModelAndView容器，用于承载整个处理过程中对返回结果的Model与View的修改，即与Model、View相关的读写逻辑都通过ModelAndView容器执行
			// 创建ModelAndView容器，构造时其内部已经创建了用于保存Model属性的ModelMap实例
			ModelAndViewContainer mavContainer = new ModelAndViewContainer();
			// 把重定向输入的FlashMap中所有属性添加到当前ModelAndView容器的Model属性中，以供本次处理逻辑使用
			mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
			// 这里initModel()方法主要作用是调用前面获取到的@ModelAttribute标注的方法，从而达到@ModelAttribute标注的方法能够在目标Handler调用之前调用的目的
			modelFactory.initModel(webRequest, mavContainer, invocableMethod);
			// 设置容器的属性，在重定向时忽略默认Model中的属性，只保留重定向的Model属性。Model属性默认为true，如果不忽略，默认Model中的属性将通过url的路径参数传递
			mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);

			// 在调用完使用上述方法之后，Spring会判断当前handler的返回值是否为WebAsyncTask或DefferredResult类型，如果是这两种类型的一种，那么就会将这些任务放入一个线程池中进行异步调用，
			// 而当前线程则可以继续进行请求的分发。这里这种设计的目的是，默认情况下Spring处理请求都是同步的，也就是说进行请求分发的线程是会调用用户所声明的handler方法的，那么如果用户声明的handler
			// 执行时间较长，就可能导致Spring用于请求处理的线程都耗在了处理这些业务代码上，也就导致后续的请求必须等待，这在高并发的场景中是不能被允许的，因而这里Spring提供了一种异步任务处理的方式，
			// 也就是进行请求分发的线程只需要将用户的业务任务放到线程池中执行即可，其自身可以继续进行其他的请求的分发。如果线程池中的任务处理完成，其会通知Spring将处理结果返回给调用方。关于异步任务的
			// 处理流程

			// 获取当前的AsyncWebRequest，这里AsyncWebRequest的主要作用是用于判断目标handler的返回值是否为WebAsyncTask或DefferredResult，如果是这两种中的一种，
	        // 则说明当前请求的处理应该是异步的。所谓的异步，指的是当前请求会将Controller中封装的业务逻辑放到一个线程池中进行调用，待该调用有返回结果之后再返回到response中。
	        // 这种处理的优点在于用于请求分发的线程能够解放出来，从而处理更多的请求，只有待目标任务完成之后才会回来将该异步任务的结果返回。

			// 根据当前请求与响应创建异步请求
			AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(request, response);
			// 设置异步请求的超时时间为当前组件中配置的超时时间
			asyncWebRequest.setTimeout(this.asyncRequestTimeout);

			// 封装异步任务的线程池，request和interceptors到WebAsyncManager中
			WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
			// 设置异步管理器的任务执行器为当前组件中配置的任务执行器
			asyncManager.setTaskExecutor(this.taskExecutor);
			// 设置异步管理器管理的异步请求实例
			asyncManager.setAsyncWebRequest(asyncWebRequest);
			// 向异步管理器中注册Callable拦截器，Callable拦截器来自于当前组件的配置
			asyncManager.registerCallableInterceptors(this.callableInterceptors);
			// 向异步管理器中注册DeferredResult拦截器，DeferredResult拦截器来自于当前组件的配置
			asyncManager.registerDeferredResultInterceptors(this.deferredResultInterceptors);

			// 这里就是用于判断当前请求是否有异步任务结果了，如果存在，则对异步任务结果进行封装
			if (asyncManager.hasConcurrentResult()) {
				// 则获取异步执行结果
				Object result = asyncManager.getConcurrentResult();
				// 获取异步结果上下文中维护的ModelAndViewContainer
				mavContainer = (ModelAndViewContainer) asyncManager.getConcurrentResultContext()[0];
				// 清理异步管理器的结果，减少内存占用
				asyncManager.clearConcurrentResult();
				if (logger.isDebugEnabled()) {
					logger.debug("Found concurrent result value [" + result + "]");
				}
				// 封装异步任务的处理结果，虽然封装的是一个HandlerMethod，但只是Spring简单的封装的一个Callable对象，该对象中直接将调用结果返回了。
				// 这样封装的目的在于能够统一的进行右面的ServletInvocableHandlerMethod.invokeAndHandle()方法的调用
				invocableMethod = invocableMethod.wrapConcurrentResult(result);
			}

			// 对请求参数进行处理，调用目标HandlerMethod，并且将返回值封装为一个ModelAndView对象
			invocableMethod.invokeAndHandle(webRequest, mavContainer);
			// 如果处理完成后，开启了异步请求并在处理中，说明返回值为一个异步的结果，直接返回null，等待异步结果返回，再执行上面的获取异步结果逻辑
			if (asyncManager.isConcurrentHandlingStarted()) {
				return null;
			}

			// 对封装的ModelAndView进行处理，主要是判断当前请求是否进行了重定向，如果进行了重定向，还会判断是否需要将FlashAttributes封装到新的请求中
			return getModelAndView(mavContainer, modelFactory, webRequest);
		}
		finally {
			// 调用request destruction callbacks和对SessionAttributes进行处理
			webRequest.requestCompleted();
		}
	}

	/**
	 * Create a {@link ServletInvocableHandlerMethod} from the given {@link HandlerMethod} definition.
	 * @param handlerMethod the {@link HandlerMethod} definition
	 * @return the corresponding {@link ServletInvocableHandlerMethod} (or custom subclass thereof)
	 * @since 4.2
	 */
	protected ServletInvocableHandlerMethod createInvocableHandlerMethod(HandlerMethod handlerMethod) {
		return new ServletInvocableHandlerMethod(handlerMethod);
	}

	/**主要工作还是获取当前需要先于目标handler执行的方法，并且获取的方式与前面的InitBinder非常的相似。关于这里获取的方法，其具体的执行过程实际上是在后面的ModelFactory.initModel()方法中进行
	 * @param handlerMethod 处理器方法
	 * @param binderFactory WebDataBinder工厂
	 * @return
	 */
	private ModelFactory getModelFactory(HandlerMethod handlerMethod, WebDataBinderFactory binderFactory) {
		// 获取SessionAttributes的处理器，用于处理处理器bean类型上标记的@SessionAttribute注解
		// 这里SessionAttributeHandler的作用是声明几个属性，使其能够在多个请求之间共享，并且其能够保证当前request返回的model中始终保有这些属性
		SessionAttributesHandler sessionAttrHandler = getSessionAttributesHandler(handlerMethod);
		// 获取处理器的bean类型
		Class<?> handlerType = handlerMethod.getBeanType();
		// 判断缓存中是否保存有当前handler执行之前所需要执行的标注了@ModelAttribute的方法
		Set<Method> methods = this.modelAttributeCache.get(handlerType);
		if (methods == null) {
			// 如果缓存中没有相关属性，那么就在当前bean中查找所有使用@ModelAttribute标注，但是没有使用@RequestMapping标注的方法，并将这些方法缓存起来
			methods = MethodIntrospector.selectMethods(handlerType, MODEL_ATTRIBUTE_METHODS);
			// 放入缓存加快下次处理
			this.modelAttributeCache.put(handlerType, methods);
		}
		// 获取全局的使用@ModelAttribute标注，但是没有使用@RequestMapping标注的方法，这里全局类型的方法的声明方式需要注意的是，其所在的bean必须使用@ControllerAdvice进行标注
		List<InvocableHandlerMethod> attrMethods = new ArrayList<InvocableHandlerMethod>();
		// 全局的@ControllerAdvice标记的处理器增强中的@ModelAttribute方法优先
		// 遍历处理器增强bean中的@ModelAttribute注解方法缓存，该缓存内容在组件初始化时填充，class是对应的处理器增强bean的封装：ControllerAdviceBean，methodSet是这个处理器增强bean中的全部@ModelAttribute标记的方法
		for (Entry<ControllerAdviceBean, Set<Method>> entry : this.modelAttributeAdviceCache.entrySet()) {
			// 判断@ControllerAdvice中指定的作用的bean范围与当前bean是否匹配，匹配了才会对其应用
			if (entry.getKey().isApplicableToBeanType(handlerType)) {
				// 解析处理器增强bean为实例(这里一般是把beanName解析为bean)
				Object bean = entry.getKey().resolveBean();
				for (Method method : entry.getValue()) {
					attrMethods.add(createModelAttributeMethod(binderFactory, bean, method));
				}
			}
		}
		// 将当前方法中使用@ModelAttribute标注的方法添加到需要执行的attrMethods中。从这里的添加顺序可以看出，全局类型的方法将会先于局部类型的方法执行
		for (Method method : methods) {
			Object bean = handlerMethod.getBean();
			attrMethods.add(createModelAttributeMethod(binderFactory, bean, method));
		}
		// 将需要执行的方法等数据封装为ModelFactory对象
		return new ModelFactory(attrMethods, binderFactory, sessionAttrHandler);
	}

	/**对@ModelAttribute注解标记的Model初始化方法创建一个可调用方法的封装
	 * @param factory
	 * @param bean
	 * @param method
	 * @return
	 */
	private InvocableHandlerMethod createModelAttributeMethod(WebDataBinderFactory factory, Object bean, Method method) {
		// 先创建一个实例
		InvocableHandlerMethod attrMethod = new InvocableHandlerMethod(bean, method);
		// 该可调用方法内部使用的参数解析器与处理器方法使用的参数解析器相同，与@InitBinder使用的参数解析器不同
		attrMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
		// 同样的参数名侦测器组件
		attrMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);
		// 设置WebDataBinder工厂，此处使用与处理器方法相同的WebDataBinder工厂，即在上一步的获取WebDataBinder工厂逻辑中获取的工厂
		attrMethod.setDataBinderFactory(factory);
		return attrMethod;
	}

	/** 这里获取InitBinder的方式主要有两种，一种是获取全局配置的InitBinder，全局类型的InitBinder需要声明的类上使用@ControllerAdvice进行标注，并且声明方法上使用@InitBinder进行标注；
	 * <br/>另一种则是获取当前handler所在类中的使用@InitBinder注解标注的方法。这两种InitBinder都会执行，只不过全局类型的InitBinder会先于局部类型的InitBinder执行。
	 * <br/>关于使用@InitBinder标注的方法的执行时间点，需要说明的是，因为其与参数绑定有关，因而其只会在参数绑定时才会执行
	 * @param handlerMethod
	 * @return
	 * @throws Exception
	 */
	private WebDataBinderFactory getDataBinderFactory(HandlerMethod handlerMethod) throws Exception {
		// 获取处理器方法所在的bean类型
		Class<?> handlerType = handlerMethod.getBeanType();
		// 判断当前缓存中是否缓存了当前bean所需要装配的InitBinder方法，如果存在，则直接从缓存中取，如果不存在，则在当前bean中进行扫描获取
		// initBinderCache缓存当前bean里的@InitBinder注解标识的方法
		Set<Method> methods = this.initBinderCache.get(handlerType);
		if (methods == null) {
			// 在当前bean中查找所有标注了@InitBinder注解的方法，这里INIT_BINDER_METHODS就是一个选择器，表示只获取使用@InitBinder标注的方法
			methods = MethodIntrospector.selectMethods(handlerType, INIT_BINDER_METHODS);
			// 添加到缓存，以提高后续的处理速度
			this.initBinderCache.put(handlerType, methods);
		}
		// 用于保存全部标记了@InitBinder方法的结果列表，此处注意：Method最终都被包装成了InvocableHandlerMethod，从而具有执行的能力
		List<InvocableHandlerMethod> initBinderMethods = new ArrayList<InvocableHandlerMethod>();
		// 上面找了本类的InitBinder，现在开始看看全局里有木有@InitBinder，这里initBinderAdviceCache是在RequestMappingHandlerAdapter初始化时同步初始化的。
	    // Global methods first（先把全局的放进去，再放个性化的~~~~ 所以小细节：有覆盖的效果哟~~~）
	    // initBinderAdviceCache它是一个缓存LinkedHashMap(有序哦~~~)，缓存着作用于全局的类。
	    // 如@ControllerAdvice，注意和`RequestBodyAdvice`、`ResponseBodyAdvice`区分开来
	    // methodSet：说明一个类里面是可以定义N多个标注有@InitBinder的方法~~~~~
		// 1、Global methods first
		for (Entry<ControllerAdviceBean, Set<Method>> entry : this.initBinderAdviceCache.entrySet()) {
			// 这里判断的是当前配置的全局类型的InitBinder是否能够应用于当前bean，判断的方式主要在@ControllerAdvice注解中进行了声明，包括通过包名，类所在的包，接口或者注解的形式限定的范围
			if (entry.getKey().isApplicableToBeanType(handlerType)) {
				// 这个resolveBean() 有点意思：它持有的Bean若是个BeanName的话，会getBean()一下的
                // 大多数情况下都是BeanName，这在@ControllerAdvice的初始化时会讲~~~
				Object bean = entry.getKey().resolveBean();
				for (Method method : entry.getValue()) {
					// createInitBinderMethod：把bean实例和Method适配为可执行的InvocableHandlerMethod
                    // 特点是把本类的HandlerMethodArgumentResolverComposite传进去了，当然还有DataBinderFactory和ParameterNameDiscoverer等
					initBinderMethods.add(createInitBinderMethod(bean, method));
				}
			}
		}
		// 2. 这里是将当前HandlerMethod所在bean中的InitBinder添加到需要执行的initBinderMethods中。这里从添加的顺序可以看出，全局类型的InitBinder会在当前bean中的InitBinder之前执行
		for (Method method : methods) {
			Object bean = handlerMethod.getBean();
			initBinderMethods.add(createInitBinderMethod(bean, method));
		}
		// 将需要执行的InitBinder封装到InitBinderDataBinderFactory中
		return createDataBinderFactory(initBinderMethods);
	}

	/**创建InitBinder的可调用处理器方法实例，传入参数是方法所在bean实例与@InitBinder标记的方法
	 * @param bean
	 * @param method
	 * @return
	 */
	private InvocableHandlerMethod createInitBinderMethod(Object bean, Method method) {
		// 创建binder方法实例
		InvocableHandlerMethod binderMethod = new InvocableHandlerMethod(bean, method);
		// 设置binder方法的方法参数解析器为当前RequestMappingHandlerAdapter组件内初始化的InitBinder参数解析器
		binderMethod.setHandlerMethodArgumentResolvers(this.initBinderArgumentResolvers);
		// 设置binder方法的WebDataBinder工厂，和处理器方法的WebDataBinder工厂不是同一个，
		// 此处的WebDataBinder工厂仅执行一部分初始化功能，后续使用的WebDataBinder则为当前获取工厂逻辑中返回的工厂实例，包含了@InitBinder相关初始化逻辑的工厂
		// 传入了本组件内配置的webBindingInitializer，是一个全局的WebDataBinder初始化器，用于从工厂获取WebDataBinder时为其设置一些全局的组件，如validator校验器与conversionService类型转换服务等
		binderMethod.setDataBinderFactory(new DefaultDataBinderFactory(this.webBindingInitializer));
		// 设置参数名获得器为当前组件配置的参数名获得器
		binderMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);
		return binderMethod;
	}

	/**创建WebDataBinder工厂方法
	 * <br/>Template method to create a new InitBinderDataBinderFactory instance.
	 * <p>The default implementation creates a ServletRequestDataBinderFactory.
	 * This can be overridden for custom ServletRequestDataBinder subclasses.
	 * @param binderMethods {@code @InitBinder} methods
	 * @return the InitBinderDataBinderFactory instance to use
	 * @throws Exception in case of invalid state or arguments
	 */
	protected InitBinderDataBinderFactory createDataBinderFactory(List<InvocableHandlerMethod> binderMethods) throws Exception {
		// 直接创建ServletRequestDataBinderFactory类型的WebDataBinder工厂，封装所有的@InitBinder方法，同时传入当前组件配置的webBindingInitializer，用于从工厂创建WebDataBinder时，使用这个WebDataBinder初始化器对创建的WebDataBinder进行初始化
		return new ServletRequestDataBinderFactory(binderMethods, getWebBindingInitializer());
	}

	/**在处理器方法调用后，又对处理器方法的返回值做了处理，最后还少一个整合的部分。因为处理适配器的处理方法最终返回的类型应该是ModelAndView的封装类型，而在调用处理器方法的整个过程中，并没有这种类型的返回值被创建。
	 * <br/>但是在整个处理过程中，使用了同一个ModelAndView容器，所有的处理结果也都放在了这个容器中
	 * @param mavContainer
	 * @param modelFactory
	 * @param webRequest
	 * @return
	 * @throws Exception
	 */
	private ModelAndView getModelAndView(ModelAndViewContainer mavContainer, ModelFactory modelFactory, NativeWebRequest webRequest) throws Exception {
		// 调用Model工厂的更新模型方法，用于把处理过程中产生的一些Model属性保存在session中或者清理一些session值，以及添加参数绑定的BindingResult到Model属性中。
		// 当处理器方法参数引入的SessionStatis参数被标记为已完成，则执行SessionAttributes处理器的清理操作，把该处理器放入session中的值删除；
		// 否则会把当前Model中与SessionAttributes处理器对应的的@SessionAttributes注解声明的names或types匹配的属性添加到session中供后续请求使用
		modelFactory.updateModel(webRequest, mavContainer);
		// 如果是已经处理过的请求，则返回的ModelAndView为null，后续不再执行处理
		if (mavContainer.isRequestHandled()) {
			// json的处理在这里返回
			return null;
		}
		// 获取ModelAndView容器中的ModelMap，包含了所有的Model属性
		ModelMap model = mavContainer.getModel();
		// 使用容器中的视图名、所有Model属性Map、容器中设置的响应状态码创建ModelAndView结果，该状态码如果不为空，会覆盖@ResponseStatus注解声明的状态码
		ModelAndView mav = new ModelAndView(mavContainer.getViewName(), model, mavContainer.getStatus());
		// 如果容器中的视图不是视图名引用
		if (!mavContainer.isViewReference()) {
			// 则直接设置返回ModelAndView中的视图
			mav.setView((View) mavContainer.getView());
		}
		// 如果模型属性是RedirectAttributes类型，说明是通过RedirectAttributes类型引入的参数添加的模型属性值，即重定向属性
		if (model instanceof RedirectAttributes) {
			// 则获取重定向模型属性中需要留给重定向后请求使用的闪存属性
			Map<String, ?> flashAttributes = ((RedirectAttributes) model).getFlashAttributes();
			// 通过传入的请求封装获取原始的请求
			HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
			// 把重定向的删除属性添加到当前请求的输出FlashMap中
			RequestContextUtils.getOutputFlashMap(request).putAll(flashAttributes);
		}
		// 最后返回这个ModelAndView结果
		return mav;
	}

}
